/** @format */

import * as CryptoJS from 'crypto-js';

// param 请求对象, appKey密钥
export function enedSign(param: any, appKey: string, method: string): string {
  //将十六进制编码的密文字符串转换为密码params对象。`
  const key = CryptoJS.enc.Utf8.parse(appKey);
  //将十六进制编码的密文字符串转换为密码params对象。
  if (param.sign) {
    delete param.sign;
  }
  console.log(param);
  //对象用“,”隔开，字段之前用"&"隔开
  const content = CryptoJS.enc.Utf8.parse(sortJoin(param, "&"));
  console.log(sortJoin(param, "&"));
  //生成密钥
  const value = CryptoJS.HmacSHA1(content, key);
  //将密钥转换为Base64字符串，生成签名
  const signs = CryptoJS.enc.Base64.stringify(value);
  console.log(signs);
  //处理签名中的特殊字符
  if (method === "get" || method === "delete") {
    const sign = encodeURIComponent(signs);
    return sign;
  } else {
    return signs;
  }
}

export function sortJoin(obj:any, prefix:any) {
  if (obj == null) return "";
  //返回对象的可枚举属性和方法的名称。
  let keys = Object.keys(obj);
  // 比较用于确定元素顺序的函数的名称。如果省略，则按升序ASCII字符顺序对元素排序。
  keys = keys.sort();
  let ret = "";
  for (let i = 0; i < keys.length; i++) {
    if (ret != "") {
      ret += prefix;
    }
    ret += keys[i];
    ret += "=";
    const val = obj[keys[i]];
    //判断是否为复杂对象（对象是否包含数组）
    if (val instanceof Array) {
      ret += "[";
      ret += sortArrayJoin(val, ",");
      ret += "]";
    } else if (val instanceof Object) {
      ret += "{";
      ret += sortJoin(val, prefix);
      ret += "}";
    } else {
      ret += val === null ? "" : val;
    }
  }

  return ret;
}

export function sortArrayJoin(arr:any, prefix:any) {
  if (!(arr instanceof Array)) {
    throw new Error("the argument [arr] must be array.");
  }
  arr = arr.sort();
  let ret = "";
  for (let i = 0; i < arr.length; i++) {
    if (ret != "") {
      ret += prefix;
    }
    const val = arr[i];
    if (val instanceof Array) {
      ret += "[";
      ret += sortArrayJoin(val, prefix);
      ret += "]";
    } else if (val instanceof Object) {
      ret += "{";
      ret += sortJoin(val, "&");
      ret += "}";
    } else {
      ret += val === null ? "" : val;
    }
  }
  return ret;
}
